home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Travel to Space
/
Travel to Space.iso
/
dos_prog
/
astronmy
/
geosat
/
geosat.pas
< prev
Wrap
Pascal/Delphi Source File
|
1990-10-16
|
14KB
|
461 lines
{$A+,B-,D+,E+,F-,I-,L+,N+,O-,R-,S-,V-}
{$M 16384,0,655360}
(*
Program 'GEOSAT'
Adapted to Turbo Pascal on October 13, 1990
by Philip Miller
from
the Quick Basic Program
Copyright (C) 1982 by David Eagle
Public domain for the IBM-PC on October 8, 1986
Computes direction of geosynchronous satellites
Azimuth angle : Positive clockwise from north ( degrees )
Elevation angle : Positive above the horizon ( degrees )
*)
{ ********************************************************** }
Program GeoSat;
Uses OpCrt,
OpString,
OpDate;
{$I FLOAT.INC} (* determines float type real or double *)
Type
SatRecType = Record
Bird : String[12];
Code : String[4];
Geolong : String[5];
Az : String[13];
Alt : String[13];
end;
VAR
A,B,C,D,R : FLOAT;
I, J, K : Integer;
HalfPi : Float;
DTR : Float;
RTD : Float;
LV : ARRAY[1..3] OF FLOAT;
UP : ARRAY[1..3] OF FLOAT;
OBSLAT : FLOAT;
OBSLONG : FLOAT;
OBSALT : FLOAT;
XOBS : FLOAT;
YOBS : FLOAT;
ZOBS : FLOAT;
AZIMUTH : FLOAT;
ELEVATION : FLOAT;
SATLONG : Float;
OBSLATstr : String;
OBSLONGstr : String;
OBSALTstr : String;
AZIMUTHstr : String;
ELEVATIONstr : String;
SATLONGstr : String;
SatRec : Array[ 1..30 ] of SatRecType;
MaxRecs : Byte;
HelpAttr : Word;
HeadAttr : Word;
TitleAttr: Word;
DispAttr : Word;
LabelAttr: Word;
CONST
RREQ = 1 / 637814;
FLAT = 1 / 298.257;
HGEO = 6.6107426;
SATFILE = 'GEOSAT.DAT';
{ *************************************************************** }
Procedure SetColors; { This a TURBO-POWER(r) library routine }
{-Choose attributes for display}
Begin
case CurrentMode of
3 :
Begin
HelpAttr := $1A; { all regular screen colors }
HeadAttr := $1F; { top header colors }
TitleAttr:= $1B; { scroll bar colors }
DispAttr := $1E; { category header colors }
LabelAttr:= $1C;
TextAttr := $1E; { large frame color }
end;
ELSE
Begin
HelpAttr := $07;
HeadAttr := $0F;
TitleAttr:= $0F;
DispAttr := $07;
LabelAttr:= $0F;
TextAttr := $07;
end;
end;
end;
Procedure Init;
Begin
SetColors;
HalfPi := 0.5 * PI;
DTR := PI / 180;
RTD := 180 / PI;
FillChar( SatRec, Sizeof( SatRec ), #0 );
A := 0;
B := 0;
C := 0;
D := 0;
R := 0;
end;
Function Sgn( ww : float ) : float;
Begin
IF WW < 0 THEN
SGN := -1
ELSE
SGN := +1;
end;
Procedure ATAN3( AA : float;
BB : float;
var CC : float ); { 4-quadrant arc tangent subroutine }
Begin
IF ABS(AA) < 1E-8 THEN
Begin
CC := (1-SGN(BB)) * HalfPi;
EXIT;
end
ELSE
CC := ( 2 - SGN(AA)) * HalfPi;
IF ABS(BB) < 1E-8 THEN
EXIT
ELSE
CC := CC + SGN(AA) * SGN(BB) * ( ABS( ArcTan( AA/BB ) ) - HalfPi );
end;
Function AzQuad16( vAZ : float ) : string;
Begin
IF (vAZ >= 0 ) and (vAZ < 11.25 ) OR
(vAZ >= 371.25) and (vAZ <= 360) THEN
AzQuad16 := ' (N) '
ELSE IF ( vAZ >= 11.25) and (vAZ < 33.75) THEN
AzQuad16 := ' (NNE)'
ELSE IF ( vAZ >= 33.75) and (vAZ < 56.25) THEN
AzQuad16 := ' (NE) '
ELSE IF ( vAZ >= 56.25) and (vAZ < 78.75) THEN
AzQuad16 := ' (ENE)'
ELSE IF ( vAZ >= 78.75) and (vAZ < 101.25) THEN
AzQuad16 := ' (E) '
ELSE IF ( vAZ >= 101.25) and (vAZ < 123.75) THEN
AzQuad16 := ' (ESE)'
ELSE IF ( vAZ >= 123.75) and (vAZ < 146.25) THEN
AzQuad16 := ' (SE) '
ELSE IF ( vAZ >= 146.25) and (vAZ < 168.75) THEN
AzQuad16 := ' (SSE)'
ELSE IF ( vAZ >= 168.75) and (vAZ < 191.25) THEN
AzQuad16 := ' (S) '
ELSE IF ( vAZ >= 191.25) and (vAZ < 213.75) THEN
AzQuad16 := ' (SSW)'
ELSE IF ( vAZ >= 213.75) and (vAZ < 236.25) THEN
AzQuad16 := ' (SW) '
ELSE IF ( vAZ >= 236.25) and (vAZ < 258.75) THEN
AzQuad16 := ' (WSW)'
ELSE IF ( vAZ >= 258.75) and (vAZ < 281.25) THEN
AzQuad16 := ' (W) '
ELSE IF ( vAZ >= 281.25) and (vAZ < 303.75) THEN
AzQuad16 := ' (WNW)'
ELSE IF ( vAZ >= 303.75) and (vAZ < 326.25) THEN
AzQuad16 := ' (NW) '
ELSE IF ( vAZ >= 326.25) and (vAZ < 348.75) THEN
AzQuad16 := ' (NNW)';
end;
Procedure OBSVECTOR; { Observer position vector subroutine }
VAR
E : Float;
F : Float;
G : Float;
H : Float;
Begin
A := OBSLAT * DTR;
B := SIN(A);
C := COS(A);
D := 1 - FLAT;
E := SQRT( 1 - (2 * FLAT - SQR(FLAT) ) * SQR(B) );
F := 1 / E + OBSALT * RREQ;
G := SQR(D)/E + OBSALT * RREQ;
H := -OBSLONG*DTR;
XOBS := F * C * COS(H);
YOBS := F * C * SIN(H);
ZOBS := G*B;
end;
Procedure TOPOCENTRIC; { Convert to topocentric coordinates }
VAR
MATRIX : ARRAY[1..3,1..3] OF FLOAT;
Begin
A := SIN( OBSLAT*DTR );
B := COS( OBSLAT*DTR );
C := SIN( -OBSLONG*DTR );
D := COS( -OBSLONG*DTR );
MATRIX[1,1] := A*D;
MATRIX[1,2] := A*C;
MATRIX[1,3] := -B;
MATRIX[2,1] := -C;
MATRIX[2,2] := D;
MATRIX[2,3] := 0;
MATRIX[3,1] := B*D;
MATRIX[3,2] := B*C;
MATRIX[3,3] := A;
FOR I := 1 TO 3 Do
Begin
A := 0;
FOR J := 1 TO 3 Do
A := A + MATRIX[I,J] * UP[J];
LV[I] := A;
end;
IF ABS( LV[3] ) > 1 THEN
ELEVATION := SGN( LV[3] ) * 90
ELSE
ELEVATION := ( ArcTan( LV[3] / SQRT( 1 - SQR(LV[3]) ) ) ) * RTD;
A := LV[2];
B := -LV[1];
ATAN3(A,B,C);
AZIMUTH := RTD*C;
ELEVATIONstr := Form( '###.##', ELEVATION );
AZIMUTHstr := Form( '###.##', AZIMUTH );
end;
Procedure PAUSE; { Screen pause }
var
Dummy : char;
Begin
gotoXY( 25, 24 );
Dummy := #0;
FastCenter( '< Press Any Key To Continue... >', 25, HeadAttr );
Dummy := ReadKey;
Repeat Until dummy <> '';
end;
Procedure INTRODUCTION; { Program introduction subroutine }
Begin
ClrScr; { Uses some TURBO-POWER(r) ROUTINES }
FastWrite( 'Program "GEOSAT" is an interactive TURBO-PASCAL program which can ', 4,5,HelpAttr );
FastWrite( 'be used to determine both the azimuth and elevation siting angles ', 5,5,HelpAttr );
FastWrite( 'for a satellite dish located in North America pointing at the various ', 6,5,HelpAttr );
FastWrite( 'geosynchronous satellites. The program takes into account the ', 7,5,HelpAttr );
FastWrite( 'effect of the flattening or ''oblateness'' of the earth on the ', 8,5,HelpAttr );
FastWrite( 'observer location on the earth. It also compensates for ''non-sea'' ', 9,5,HelpAttr );
FastWrite( 'level observation and dish sites. These features provide the user ', 10,5,HelpAttr );
FastWrite( 'with very accurate pointing angles. ', 11,5,HelpAttr );
FastCenter( 'USER INPUTS AND SELECTIONS' ,13, HeadAttr );
FastWrite( 'The program GEOSAT will prompt the user for geographic coordinates to ' ,15,5,HelpAttr );
FastWrite( 'convert geosyncronous longitude to topocentric (earth) coordinates ' ,16,5,HelpAttr );
FastWrite( 'The following describes the necessary input. ' ,17,5,HelpAttr );
PAUSE;
ClrScr;
{} FastWrite( 'Observer Latitude (degrees):' , 4,5,HeadAttr );
FastWrite( 'The user should respond with the geographic latitude in decimal ' , 5,5,HelpAttr );
FastWrite( 'degrees taking note of the sign convention. For example, an ' , 6,5,HelpAttr );
FastWrite( 'observer at 36 degrees, 30 minutes north latitude would input 36.5.' , 7,5,HelpAttr );
{} FastWrite( 'Observer West Longitude (degrees):' , 9,5,HeadAttr );
FastWrite( 'Input the observer West longitude in decimal degrees. This will ' ,10,5,HelpAttr );
FastWrite( 'always be a positive number. ' ,11,5,HelpAttr );
{} FastWrite( 'Observer altitude (meters):' ,14,5,HeadAttr );
FastWrite( 'Input your altitude (height from sea level) at the above location ' ,15,5,HelpAttr );
FastWrite( 'in meters. Sites above sea level are input as positive numbers and ' ,16,5,HelpAttr );
FastWrite( 'those below sea level are negative numbers. ' ,17,5,HelpAttr );
PAUSE;
Clrscr;
{} FastCenter( 'PROGRAM OUTPUT' , 4, HeadAttr );
FastWrite( '"GEOSAT" will output the observer-centered or topocentric azimuth ', 6,5,HelpAttr );
FastWrite( 'and elevation angles at the Satellite Dish location for all the ', 7,5,HelpAttr );
FastWrite( 'North American Satellites. Azimuth is measured positive clockwise ', 8,5,HelpAttr );
FastWrite( 'from North and elevation is positive above the observer''s horizon.', 9,5,HelpAttr );
FastWrite( 'For example, an Azimuth reading of 90° is EAST and 180° is SOUTH. ',10,5,HelpAttr );
FastWrite( 'Elevation angles which are negative indicate that the satellites ',11,5,HelpAttr );
FastWrite( 'are below the horizon and therefore cannot be seen from an ',12,5,HelpAttr );
FastWrite( 'observer''s location. Angles are printed in decimal degrees. ',13,5,HelpAttr );
PAUSE;
end;
Procedure Calculate_Obs_Position; { Calculate observer's position}
var
X3 : Float;
Y3 : Float;
Z3 : Float;
XSAT : Float;
YSAT : Float;
Begin
OBSVECTOR; { Calculate Satellite's Position }
A := -SATLONG*DTR;
XSAT := HGEO * COS(A);
YSAT := HGEO * SIN(A);
{ Calculate Pointing Angles to Satellite }
X3 := XSAT - XOBS;
Y3 := YSAT - YOBS;
Z3 := -ZOBS;
R := SQRT( SQR(X3) + SQR(Y3) + SQR(Z3) );
UP[1] := X3/R;
UP[2] := Y3/R;
UP[3] := Z3/R;
TOPOCENTRIC;
end;
Procedure Display_Results;
Begin { Print or display results}
ClrScr;
FastWrite( 'Observers Location:' , 7, 61, TitleAttr );
FastWrite( 'Latitude: ' + OBSLATstr , 8, 61, HeadAttr );
FastWrite( 'West Long: ' + OBSLONGstr , 9, 61, HeadAttr );
FastWrite( 'Altitude: ' + OBSALTstr ,10, 61, TitleAttr );
FastWrite( 'SAT NAME CODE GEOSYNCH AZIMUTH ELEVATION', 1,4, LabelAttr );
FOR J := 1 TO MaxRecs DO { was 20 - now determined by reading }
With SatRec[J] DO
FastWrite( Bird + ' ' + Code + ' ' + Geolong + '° '
+ Az + ' '+ Alt , J+1, 4, TextAttr );
PAUSE;
end; {Display_Results}
Procedure MainProgram;
Label
Location,
Satellite,
Main;
Var
INTRO : Char;
REPLY : Char;
FP : Text;
Begin
Init; { Init variables, set colors }
ClrScr;
FastCenter( ' GEO-SAT -- SYNCRONOUS SATELLITE POSTIONS ', 2,HeadAttr );
FastCenter( ' (C) Copyright 1990 by Philip Miller ', 3,TitleAttr );
FastWrite( 'Program introduction ( <Y>es, <N>o )', 5,5,TitleAttr );
gotoXY( 45, 5 );
INTRO := ReadKey;
IF INTRO in ['y','Y'] THEN
Begin
HIDDENCURSOR;
INTRODUCTION;
NORMALCURSOR;
END;
MAIN:
ClrScr;
FastCenter( 'Program SYNCSAT' , 2, LabelAttr );
LOCATION:
FastWrite( 'Observer latitude ( -90° to +90° ) ' , 4, 5, TitleAttr );
gotoXY( 45, 4 );
Readln( OBSLAT );
OBSLATstr := Form( '###.##°', OBSLAT );
FastWrite( 'Observer WEST Longitude ( 0° to 360° ) ' , 6,5, TitleAttr );
gotoXY( 45, 6 );
Readln( OBSLONG );
OBSLONGstr := Form( '###.##°', OBSLONG );
FastWrite( 'Observer altitude ( meters ) ', 8,5, TitleAttr );
FastWrite( '< Above or below sea level > ', 9,5, HelpAttr );
gotoXY( 45, 8 );
Readln( OBSALT );
OBSALTstr := Form( '###.## m.', OBSALT );
{ Read data from SAT.DAT file }
SATELLITE:
ASSIGN( FP, SATFILE );
RESET( FP );
J := 0;
WHILE NOT EOF( FP ) DO
Begin
WHILE NOT EOLN( FP ) DO
Begin
INC(J);
ReadLN( FP, SatRec[J].Bird, SatRec[J].Code, SatRec[J].GeoLong );
end; { while not eoln}
end; {while not EOF}
CLOSE( FP );
MaxRecs := J;
{Calculate results into record array }
For K := 1 to MaxRecs DO { was 20 }
Begin
IF Str2Real( SatRec[K].Geolong, SATLONG ) THEN
Begin
Calculate_Obs_Position;
SatRec[K].Az := Form( '###.##°' , AZIMUTH );
SatRec[K].Az := SatRec[K].Az + AzQuad16( AZIMUTH );
SatRec[K].Alt:= Form( '####.##°' , ELEVATION);
end;
end;
HIDDENCURSOR;
Display_Results;
NORMALCURSOR;
{ Request Another Selection }
FastCenter( ' ', 25, HeadAttr );
FastWrite( 'Another location ( <Y>es, <N>o ) ' , 25,5, HelpAttr );
gotoXY( 40,25);
REPLY := ReadKey;
IF REPLY in [ 'Y', 'y' ] THEN
Begin
Clrscr;
goto LOCATION;
end
ELSE
EXIT;
end;
{ ********************* MAIN PROGRAM **********************************}
Begin
MainProgram;
ClrScr;
end.